/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#ifndef NAS_SHARE_HETRO_BACKUP_JOB_H
#define NAS_SHARE_HETRO_BACKUP_JOB_H

#include <mutex>
#include "nas_share/common/HetroCommonService.h"
#include "nas_share/common/HetroBaseStruct.h"
#include "define/Defines.h"
#include "define/Types.h"
#include "security/cmd/CmdParam.h"
#include "security/cmd/CmdExecutor.h"

class HetroBackupJob : public HetroBaseStruct, public HetroCommonService {
public:
    HetroBackupJob() {}
    ~HetroBackupJob();
    EXTER_ATTACK int PrerequisiteJob() override ;
    EXTER_ATTACK int GenerateSubJob() override ;
    EXTER_ATTACK int ExecuteSubJob() override ;
    EXTER_ATTACK int PostJob() override ;
    static int CheckBackupJobType();

    enum class SCANNER_TASK_STATUS {
        SCANNER_TASK_STATUS_INIT        = 0,
        SCANNER_TASK_STATUS_INPROGRESS  = 1,
        SCANNER_TASK_STATUS_SUCCESS     = 2,
        SCANNER_TASK_STATUS_ABORTED     = 3,
        SCANNER_TASK_STATUS_FAILED      = 4,
    };
    enum class MONITOR_BACKUP_RES_TYPE {
        MONITOR_BACKUP_RES_TYPE_SUCCESS          = 0,
        MONITOR_BACKUP_RES_TYPE_FAILED           = 1,
        MONITOR_BACKUP_RES_TYPE_ABORTED          = 2,
        MONITOR_BACKUP_RES_TYPE_NEEDRETRY        = 3
    };

public:
    /* Backup Job */
    std::shared_ptr<AppProtect::BackupJob> m_backupJobPtr {};

    std::string m_localStorageIps {};

    /* Data size copied to destination in MB */
    int64_t m_dataSize { 0 };
    std::string m_lastCopyId;

    /* Is scanner restarted */
    bool m_isScannerRestarted {false};

    /* Scanner instance */

    /* Backup instance */
    std::unique_ptr<FS_Backup::Backup> m_backup {};
    BackupPhaseStatus m_backupStatus;

    /* SubTask type: CopyPhase/DelPhase/HardLinkPhase/DirMTimePhase */
    uint32_t m_subTaskType {};

    /* Used for reporting job progress log to agent */
    ActionResult m_logResult {};
    SubJobDetails m_logSubJobDetails {};
    LogDetail m_logDetail{};
    std::vector<LogDetail> m_logDetailList;

    /* Following members are used to save final information for performance analysis */
    time_t m_startTime {};
    int32_t m_totalJobDuration {};
    int32_t m_postJobDuration {};

    /* RequestId for mainJob and subJob */
    size_t m_mainJobRequestId {};
    size_t m_subJobRequestId {};

    int64_t m_lastScannerReportTime {};
    std::atomic<bool> m_isCopying { false };
    std::atomic<bool> m_isZipSuccess { false };
    
    int m_maxSmbBlockSize = 100;

private:
    int PrerequisiteJobInner();
    int GenerateSubJobInner();
    int ExecuteSubJobInner();
    int ExecuteBackupSubJobInner(HetroBackupSubJob backupSubJob);
    int ExecuteCreateSubJobInner(HetroBackupSubJob backupSubJob);
    int ExecuteTeardownSubJobInner(HetroBackupSubJob backupSubJob);
    int ExecuteCopyMetaSubJobInner(HetroBackupSubJob backupSubJob);
    int PostJobInner();
    void InitMetaBackupFs();
    bool InitJobInfo();
    bool InitHostInfo();
    int CreatSrcDir();
    bool InitRepoPaths();
    bool PrintJobInfo();
    void PrintFilterInfo();
    bool PrintJobInfoForRepo();
    bool InitBackupCopyMetaInfo();
    bool SetupMetaFsForBackupJob();
    bool SetupDataFsForBackupJob();
    bool SetupRemoteNasForBackupJob();
    void WindupRemoteNasForBackupJob();
    bool CreateBackupCopyMetaTask();
    bool StartScanner();
    bool GetTheLastCopyId();
    void KeepPluginAlive();
    bool SkipDeleteStage(const HetroBackupSubJob& backupSubJob);
    int HandlePostJobFailed();

    template<typename... Args>
    bool ReportJobDetails(SubJobStatus::type jobStatus, int32_t jobProgress,
        std::string logLabel, const JobLogLevel::type &logLevel, Args... logArgs);
    template<typename... Args>
    bool ReportJobDetailsWithErrorCode(SubJobStatus::type jobStatus, int32_t jobProgress,
        std::string logLabel, const JobLogLevel::type &logLevel, const int64_t errCode, Args... logArgs);
    void ReportJobDetailsWithLabelAndErrcode(SubJobStatus::type jobStatus,
        const std::string& logLabel, const JobLogLevel::type &logLevel, const int64_t errCode,
        int32_t jobProgress, const std::string& message);

    bool CreateBackupJobTeardownTask();
    static void ScannerCtrlFileCallBack(void *usrData, const std::string &ControlFilePath);
    static void ScannerHardLinkCallBack(void *usrData, const std::string &ControlFilePath);
    static void BackupDirMTimeCallBack(void *usrData, const std::string &ControlFilePath);
    static void BackupDelCtrlCallBack(void *usrData, const std::string &ControlFilePath);

    bool IdentifyNasProtoVersionToUse(int64_t &errCode);
    bool CheckMountVersion(std::string proto, std::string protoVersion, int64_t &errCode);

    void FillScanConfig(ScanConfig &scanConfig);
    void FillScanConfigBasedOnEnviroment(ScanConfig &scanConfig);
    void FillScanConfigBasedOnProtocol(ScanConfig &scanConfig);
    void FillSnapDiffScanConfig(ScanConfig &scanConfig);
    void FillScanConfigForNative(ScanConfig &scanConfig) override;
    void FillScanConfigForAggr(ScanConfig &scanConfig) override;
    bool CreateSubTasksFromCtrlFile(std::string srcDir, std::string dstDir, uint32_t subTaskType, bool isFinal = false);
    bool CreateSubTasks(const std::vector<std::string>& srcFileList, const std::string& dstDir,
        uint32_t subTaskType, int64_t& lastCreateJobErrTime, bool isFinal);
    bool MonitorScanner(HetroNativeScanStatistics &scanStatistics,
        SubJobStatus::type &jobStatus, std::string &jobLogStr, int &jobProgress);
    bool ReportScannerRunningStatus(HetroNativeScanStatistics &scanStatistics);
    bool ReportScannerCompleteStatus(HetroNativeScanStatistics &scanStatistics);
    void FillBackupNFSConfig(BackupParams &backupParams);
    void FillBackupCIFSConfig(BackupParams &backupParamsb);
    void FillBackupCommonParams(BackupParams &backupParams);
    void FillAggregateBackupCommonParams(BackupParams &backupParams);

    void FillBackupConfig(BackupParams &backupParams, HetroBackupSubJob &backupSubJob);
    void FillBackupConfigPhase(BackupParams &backupParams, HetroBackupSubJob &backupSubJob);
    bool StartBackup(HetroBackupSubJob backupSubJob);
    MONITOR_BACKUP_RES_TYPE MonitorBackup(BackupStats &backupStatistics,
        SubJobStatus::type &jobStatus, std::string &jobLogStr, int &jobProgress);
    void HandleMonitorStuck(BackupStats &backupStatistics,
        SubJobStatus::type &jobStatus, std::string &jobLogLabel, int &jobProgress);
    void HandleMonitorComplete(SubJobStatus::type &jobStatus, std::string &jobLogLabel, int &jobProgress);
    void HandleMonitorFailed(SubJobStatus::type &jobStatus, std::string &jobLogLabel);
    void HandleMonitorAborted(SubJobStatus::type &jobStatus, std::string &jobLogLabel);

    void FillMonitorScannerVarDetails(SCANNER_TASK_STATUS &scanTaskStatus,
        SubJobStatus::type &jobStatus, std::string &jobLogStr, int &jobProgress);
    bool ReportBackupRunningStatus(uint64_t currSubJobDataSize);
    bool ReportBackupCompletionStatus();
    bool UpdateBackupStatistics(BackupStats &backupStatistics);
    bool CalculateJobStats();
    bool IsSubTaskStatsFileExists();
    bool UpdateBackupStartTimeInSharedResource(HetroBackupSubJob& backupSubJob);
    void CheckAndDeleteMetaFiles(const std::string& fileName);
    int ExecuteCheckSubJobInner();

    bool IsFullBackup();
    bool IsSnapshotEnabled() const;
    bool SaveScannerMeta();
    void PrintBackupCopyInfo(HetroNativeBackupStats &backupStatistics);
    void RecordTimestamp();
    void RemoveCacheDirectories();

    int callCheckCertThumbPrint(const AppProtect::ApplicationEnvironment& protectEnv);
    bool KinitTGT();

    std::string GetProtocolName(std::string protocol);
    void ReportJobProgress(SubJobStatus::type &jobStatus, std::string &jobLogLabel);
    void ReportJobCompleteStatusForGenerateJob(HetroNativeScanStatistics &scanStatistics,
         SubJobStatus::type &jobStatus, std::string &jobLogLabel, int &jobProgress);
    void FillBackupCopyParam(HetroLastCopyDetails &newBackupCopy);
    int CopyMetaFileToMetaRepo(const std::string& scanMetaFilePath);

    std::string GetSmbVersion(int64_t& errCode);
    bool CheckSmbConnectVersion(Module::SmbVersion version, int64_t &errCode);
    bool PostReportCopyAdditionalInfo();
    void BuildCopyRepositories(std::vector<StorageRepository>& repositories);
    bool UpdateCopyPhaseStartTimeInGenRsc();
    bool GenerateSubJobList(std::vector<SubJob> &subJobList, std::vector<std::string> &ctrlFileList,
        const std::string &dstCtrlFileRelPath, const std::string &ctrlFileFullPath);
    bool HandleMonitorScannerCompletion(SubJobStatus::type &jobStatus, std::string &jobLogLabel,
        const std::string &scanCtrlFilePath, const std::string &scanMetaFilePath,
        const std::string &backupCtrlFilePath);
    bool GetBackupJobInfo();
    bool IsAggregate();
    bool GetAggCopyExtendInfo(std::string& jsonString);
    bool ShouldEnableOceanStorV5Snapdiff();
    bool ShouldKeepOceanStorV5Snapshot();
    bool IsOceanStorV5IncBackup();
    bool NeedMountUseNfs4();
    bool MountNfs4ForNetapp();
    void CopyMetaFileToMetaRepoMkdir(const std::string& scanMetaFilePath);
    std::vector<Module::CmdParam> FillCopyMetaCmd(const std::string& scanMetaFilePath,
        const std::string& dirCacheZipFileName, const std::string& fCacheZipFileName,
        const std::string& metaZipFilename, const std::string& xmetaZipFileName);

private:
    std::atomic<bool> m_generateSubjobFinish { false };
    int64_t m_lastKeepAliveReportTime { 0 };
};

#endif // _NAS_SHARE_HETRO_BACKUP_JOB_H